package dgopenai

import (
	"github.com/google/uuid"
	"github.com/sashabaranov/go-openai"
)

// TemplateGenerateContentRequest represents a request to generate content using a template
type TemplateGenerateContentRequest struct {
	TemplateName   string                   `json:"templateName" remark:"模板名称"`
	TemplateParams map[string]any           `json:"templateParams" remark:"模板参数"`
	MultiContent   []openai.ChatMessagePart `json:"multiContent" remark:"多轮对话内容"`
	BizParams      map[string]any           `json:"bizParams" remark:"业务参数"`
	RequestId      string                   `json:"requestId" remark:"请求ID"`
}

// GenerateContentRequest represents a request to generate content
type GenerateContentRequest struct {
	PlatformModels []*PlatformModelPair `json:"platformModels" remark:"平台模型列表"`
	EnableThinking bool                 `json:"enableThinking" remark:"是否启用思考模式"`
	TryTimes       int                  `json:"tryTimes" remark:"尝试次数"`
	RequestId      string               `json:"requestId" remark:"请求ID"`

	Messages         []openai.ChatCompletionMessage       `json:"messages" remark:"消息列表"`
	MaxTokens        int                                  `json:"maxTokens" remark:"最大token数"`
	Temperature      float32                              `json:"temperature" remark:"温度"`
	FrequencyPenalty float32                              `json:"frequencyPenalty" remark:"频率惩罚"`
	ResponseFormat   *openai.ChatCompletionResponseFormat `json:"responseFormat" remark:"响应格式"`
	Tools            []openai.Tool                        `json:"tools" remark:"工具列表"`
}

// PlatformModelPair represents a platform and model pair
type PlatformModelPair struct {
	Platform string `json:"platform" remark:"平台"`
	Model    string `json:"model" remark:"模型"`
}

// GenerateContentResponse represents a response from generating content
type GenerateContentResponse struct {
	Platform       string               `json:"platform" remark:"平台"`
	Model          string               `json:"model" remark:"模型"`
	Content        string               `json:"content" remark:"生成内容"`
	ResponseFormat string               `json:"responseFormat" remark:"响应格式"`
	RequestId      string               `json:"requestId" remark:"请求ID"`
	Usage          *openai.Usage        `json:"usage" remark:"使用量"`
	FunctionCall   *openai.FunctionCall `json:"functionCall" remark:"函数调用"`
	FinishReason   string               `json:"finishReason" remark:"结束原因"`
}

// ChatTemplateGenerateContentRequest represents a chat request to generate content using a template
type ChatTemplateGenerateContentRequest struct {
	SessionId      int64                    `json:"sessionId" binding:"required" remark:"会话ID"`
	TemplateName   string                   `json:"templateName" remark:"模板名称"`
	TemplateParams map[string]any           `json:"templateParams" remark:"模板参数"`
	MultiContent   []openai.ChatMessagePart `json:"multiContent" remark:"多轮对话内容"`
	BizParams      map[string]any           `json:"bizParams" remark:"业务参数"`
	RequestId      string                   `json:"requestId" remark:"请求ID"`
}

// ChatRequest represents a chat request
type ChatRequest struct {
	SessionId    int64                    `json:"sessionId" binding:"required" remark:"会话ID"`
	Content      string                   `json:"content" remark:"聊天内容"`
	MultiContent []openai.ChatMessagePart `json:"multiContent" remark:"多轮对话内容"`
	Params       map[string]any           `json:"params" remark:"参数"`
	RequestId    string                   `json:"requestId" remark:"请求ID"`
}

// ChatResponse represents a chat response
type ChatResponse struct {
	Messages []*ChatMessage `json:"messages" remark:"消息列表"`
}

// ChatMessage represents a chat message
type ChatMessage struct {
	Id             int64                `json:"id" remark:"消息ID"`
	Role           string               `json:"role" remark:"角色"`
	Content        string               `json:"content" remark:"生成内容"`
	ResponseFormat string               `json:"responseFormat" remark:"响应格式"`
	FunctionCall   *openai.FunctionCall `json:"functionCall" remark:"函数调用"`
	FinishReason   string               `json:"finishReason" remark:"结束原因"`
	RequestId      string               `json:"requestId" remark:"请求ID"`
}

// buildChatCompletionRequest builds a ChatCompletionRequest from a GenerateContentRequest
func buildChatCompletionRequest(req *GenerateContentRequest) openai.ChatCompletionRequest {
	return openai.ChatCompletionRequest{
		Messages:            req.Messages,
		MaxTokens:           req.MaxTokens,
		MaxCompletionTokens: req.MaxTokens,
		Temperature:         req.Temperature,
		FrequencyPenalty:    req.FrequencyPenalty,
		ResponseFormat:      req.ResponseFormat,
		Tools:               req.Tools,
		ChatTemplateKwargs:  map[string]any{"enable_thinking": req.EnableThinking},
	}
}

// buildGenerateContentResponse builds a GenerateContentResponse from a ChatCompletionResponse
func buildGenerateContentResponse(req *GenerateContentRequest, resp *openai.ChatCompletionResponse, platformModel *PlatformModelPair) *GenerateContentResponse {
	content := resp.Choices[0].Message.Content
	content = formatLlmOutput(content)

	gcResp := &GenerateContentResponse{
		Platform:     platformModel.Platform,
		Model:        platformModel.Model,
		Content:      content,
		RequestId:    req.RequestId,
		Usage:        &resp.Usage,
		FunctionCall: resp.Choices[0].Message.FunctionCall,
		FinishReason: string(resp.Choices[0].FinishReason),
	}
	if req.ResponseFormat != nil {
		gcResp.ResponseFormat = string(req.ResponseFormat.Type)
	}

	return gcResp
}

// buildGenerateContentStreamResponse builds a GenerateContentResponse from a ChatCompletionStreamResponse
func buildGenerateContentStreamResponse(req *GenerateContentRequest, resp *openai.ChatCompletionStreamResponse) *GenerateContentResponse {
	var content string
	if len(resp.Choices) == 0 {
		content = ""
	} else {
		content = resp.Choices[0].Delta.Content
		content = formatLlmOutput(content)
	}

	gcResp := &GenerateContentResponse{
		Content:   content,
		RequestId: req.RequestId,
		Usage:     resp.Usage,
	}

	if req.ResponseFormat != nil {
		gcResp.ResponseFormat = string(req.ResponseFormat.Type)
	}

	if len(resp.Choices[0].Delta.ToolCalls) > 0 {
		gcResp.FunctionCall = &resp.Choices[0].Delta.ToolCalls[0].Function
	}

	finishReason := resp.Choices[0].FinishReason
	if finishReason == openai.FinishReasonStop || finishReason == openai.FinishReasonContentFilter {
		gcResp.FinishReason = string(finishReason)
	}

	return gcResp
}

// mergeGenerateContentResponses merges a list of GenerateContentResponse into a single response
func mergeGenerateContentResponses(respList []*GenerateContentResponse) *GenerateContentResponse {
	if len(respList) == 0 {
		return &GenerateContentResponse{}
	}

	lastIndex := len(respList) - 1
	mergedResp := &GenerateContentResponse{
		RequestId:    respList[lastIndex].RequestId,
		FinishReason: respList[lastIndex].FinishReason,
	}

	mergedUsage := &openai.Usage{}
	mergedResp.Usage = mergedUsage

	for _, resp := range respList {
		if resp.Content != "" {
			mergedResp.Content += resp.Content
		}

		if resp.FunctionCall != nil {
			if mergedResp.FunctionCall == nil {
				mergedResp.FunctionCall = resp.FunctionCall
			} else {
				mergedResp.FunctionCall.Arguments += resp.FunctionCall.Arguments
			}
		}

		if resp.Usage != nil {
			mergedUsage.PromptTokens += resp.Usage.PromptTokens
			mergedUsage.CompletionTokens += resp.Usage.CompletionTokens
			mergedUsage.TotalTokens += resp.Usage.TotalTokens
		}
	}

	return mergedResp
}

// buildChatMessageByChatRequest builds a ChatMessage from a ChatRequest
func buildChatMessageByChatRequest(req *ChatRequest) *ChatMessage {
	return &ChatMessage{
		Role:      openai.ChatMessageRoleUser,
		Content:   req.Content,
		RequestId: req.RequestId,
	}
}

// buildChatMessageByGenerateContentResponse builds a ChatMessage from a GenerateContentResponse
func buildChatMessageByGenerateContentResponse(resp *GenerateContentResponse) *ChatMessage {
	return &ChatMessage{
		Role:           openai.ChatMessageRoleAssistant,
		Content:        resp.Content,
		ResponseFormat: resp.ResponseFormat,
		FunctionCall:   resp.FunctionCall,
		FinishReason:   resp.FinishReason,
		RequestId:      resp.RequestId,
	}
}

// buildChatCompletionMessageByChatMessage builds a ChatCompletionMessage from a ChatMessage
func buildChatCompletionMessageByChatMessage(chatMessage *ChatMessage) openai.ChatCompletionMessage {
	return openai.ChatCompletionMessage{
		Role:    chatMessage.Role,
		Content: chatMessage.Content,
	}
}

// fixGenerateContentRequest fixes the GenerateContentRequest by setting default values
func fixGenerateContentRequest(req *GenerateContentRequest) {
	if req.RequestId == "" {
		req.RequestId = uuid.NewString()
	}

	if req.TryTimes < 1 {
		req.TryTimes = 1
	}
}
